package com.ibeeking.found.cop.b.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.enums.DefaultEnum;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.common.enums.SyncStatusEnum;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.cop.b.rest.service.IKfServicerService;
import com.ibeeking.found.cop.b.rest.service.IMqService;
import com.ibeeking.found.cop.b.rest.service.IWxOpenService;
import com.ibeeking.found.cop.service.common.dos.CopDepartmentDO;
import com.ibeeking.found.cop.service.common.dos.CopEmployeeDO;
import com.ibeeking.found.cop.service.common.dos.KfAccountDO;
import com.ibeeking.found.cop.service.common.dos.KfServicerDO;
import com.ibeeking.found.cop.service.common.dto.KfServicerDTO;
import com.ibeeking.found.cop.service.common.enums.MqSyncOperatorTypeEnum;
import com.ibeeking.found.cop.service.common.param.KfServicerParam;
import com.ibeeking.found.cop.service.common.param.MqSyncCopParam;
import com.ibeeking.found.cop.service.common.query.KfServicerQuery;
import com.ibeeking.found.cop.service.common.vo.KfServicerVO;
import com.ibeeking.found.cop.service.mapper.CopDepartmentMapper;
import com.ibeeking.found.cop.service.mapper.CopEmployeeMapper;
import com.ibeeking.found.cop.service.mapper.KfAccountMapper;
import com.ibeeking.found.cop.service.mapper.KfServicerMapper;
import com.ibeeking.found.id.GenerateId;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.id.IdGenerator;
import com.ibeeking.nematos.utils.json.JsonUtils;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpKfService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerOpResp;
import me.chanjar.weixin.cp.config.impl.WxCpRedissonConfigImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName KfServicerServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-27 18:50
 **/
@Service
public class KfServicerServiceImpl extends ServiceImpl<KfServicerMapper, KfServicerDO> implements IKfServicerService {

    @Resource
    private KfAccountMapper KfAccountMapper;

    @Resource
    private KfServicerMapper KfServicerMapper;

    @Resource
    private CopDepartmentMapper copDepartmentMapper;

    @Resource
    private CopEmployeeMapper copEmployeeMapper;

    @Resource
    private IWxOpenService wxOpenServiceImpl;

    @Resource
    private IMqService mqServiceImpl;

    @Override
    public List<KfServicerVO> list(KfServicerQuery query) {
        List<KfServicerDO> entityDOS = KfServicerMapper.selectList(new LambdaQueryWrapper<KfServicerDO>()
                .eq(query.getId() != null, KfServicerDO::getId, query.getId())
                .eq(query.getAccountId() != null, KfServicerDO::getAccountId, query.getAccountId())
                .eq(query.getEmployeeId() != null, KfServicerDO::getEmployeeId, query.getEmployeeId())
                .eq(query.getDepartmentId() != null, KfServicerDO::getDepartmentId, query.getDepartmentId())
                .eq(StringUtils.isNotBlank(query.getOpenKfid()), KfServicerDO::getOpenKfid, query.getOpenKfid())
                .like(StringUtils.isNotBlank(query.getEmployeeCode()), KfServicerDO::getEmployeeCode, query.getEmployeeCode())
                .eq(query.getHaveDefault() != null, KfServicerDO::getHaveDefault, query.getHaveDefault())
                .eq(query.getStatus() != null, KfServicerDO::getStatus, query.getStatus())
                .eq(query.getSyncStatus() != null, KfServicerDO::getSyncStatus, query.getSyncStatus())
                .orderByDesc(KfServicerDO::getCreateTime)
        );
        List<CopDepartmentDO> copDepartmentDOList = copDepartmentMapper.selectList(new LambdaQueryWrapper<CopDepartmentDO>());
        Map<Long, String> copDepartmentNameMaps = Collections3.isNotEmpty(copDepartmentDOList)?copDepartmentDOList.stream().collect(Collectors.toMap(CopDepartmentDO::getId, CopDepartmentDO::getName, (o, n) -> n)):null;
        List<CopEmployeeDO> copEmployeeDOList = copEmployeeMapper.selectList(new LambdaQueryWrapper<CopEmployeeDO>());
        Map<Long, String> copEmployeeNameMaps = Collections3.isNotEmpty(copEmployeeDOList)?copEmployeeDOList.stream().collect(Collectors.toMap(CopEmployeeDO::getId, CopEmployeeDO::getEmployeeName, (o, n) -> n)):null;
        List<KfServicerVO> entityVOS =JsonUtils.jsonToList(entityDOS, KfServicerVO.class);
        entityVOS.forEach(x -> {
            if(copDepartmentNameMaps!=null){
                x.setDepartmentName(copDepartmentNameMaps.get(x.getDepartmentId()));
            }
            if(copEmployeeNameMaps!=null){
                x.setEmployeeName(copEmployeeNameMaps.get(x.getEmployeeId()));
            }
            x.setHaveDefaultDesc(DefaultEnum.getDescByValue(x.getHaveDefault()));
            x.setStatusDesc(PublishStatusEnum.getName(x.getStatus()));
            x.setSyncStatusDesc(SyncStatusEnum.getName(x.getSyncStatus()));
        });
        return entityVOS;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(KfServicerParam param) {
        checkUnique(param);
        KfServicerDO entityDO = BeanUtil.convertBean(param, KfServicerDO.class);
        entityDO.setId(GenerateId.generateId());
        entityDO.setCreateBy(UserUtils.getUserId());
        entityDO.setCreateTime(LocalDateTime.now());
        entityDO.setModifyTime(LocalDateTime.now());
        entityDO.setHaveDefault(DefaultEnum.NO.getValue());
        entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
        entityDO.setStatus(PublishStatusEnum.DISABLE.getValue());
        return KfServicerMapper.insert(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(KfServicerParam param) {
        KfServicerDO entityDO = BeanUtil.convertBean(param, KfServicerDO.class);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
        return KfServicerMapper.updateById(entityDO) > 0;
    }

    @Override
    public KfServicerVO view(Long id) {
        KfServicerDO entityDO = KfServicerMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        KfServicerVO entityVO = BeanUtil.convertBean(entityDO, KfServicerVO.class);
        if(entityVO != null) {
            CopDepartmentDO copDepartmentDO = copDepartmentMapper.selectById(entityVO.getDepartmentId());
            if(copDepartmentDO !=null) {
                entityVO.setDepartmentName(copDepartmentDO.getName());
            }

            CopEmployeeDO copEmployeeDO = copEmployeeMapper.selectById(entityVO.getEmployeeId());
            if(copEmployeeDO!=null) {
                entityVO.setEmployeeName(copEmployeeDO.getEmployeeName());
            }
            entityVO.setHaveDefaultDesc(DefaultEnum.getDescByValue(entityDO.getHaveDefault()));
            entityVO.setStatusDesc(PublishStatusEnum.getName(entityDO.getStatus()));
            entityVO.setSyncStatusDesc(SyncStatusEnum.getName(entityDO.getSyncStatus()));
        }
        return entityVO;
    }

    @Override
    public KfServicerDTO queryDefaultKfServicer() {
        KfServicerDO entityDO = KfServicerMapper.selectOne(new LambdaQueryWrapper<KfServicerDO>().eq(KfServicerDO::getHaveDefault, DefaultEnum.YES.getValue()));
        if(entityDO == null)
            entityDO = KfServicerMapper.selectOne(new LambdaQueryWrapper<KfServicerDO>());
        if(entityDO == null) throw new BusinessException("没有查到相关客服接待人员信息！");
        KfServicerDTO entityDTO = BeanUtil.convertBean(entityDO, KfServicerDTO.class);
        return entityDTO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer status) {
        KfServicerDO entityDO = KfServicerMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        entityDO.setStatus(status);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        return KfServicerMapper.updateById(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        KfServicerDO entityDO = KfServicerMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        if(entityDO.getSyncStatus() == SyncStatusEnum.SYNC_YES.getValue()) {
            Integer result = this.getBean().syncKfServicerToWxCp(id, entityDO.getAccountId(),true);
            if (result <= 0) throw new BusinessException("同步删除企微的欢迎语失败，请联系管理员！");
        }
        return KfServicerMapper.deleteById(id) > 0;
    }
    /**
     * 从企业微信同步q群信息
     *
     * @param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer syncKfServicerListFromWxCp(Long accountId){
        if(accountId == null) throw new BusinessException("读取客服id参数出错");
        KfAccountDO kfAccountDo = KfAccountMapper.selectById(accountId);
        if(kfAccountDo == null) throw new BusinessException("读取客服账号不存在");
        String tenantId = UserUtils.getTenantId();
        MqSyncCopParam mqParam = new MqSyncCopParam();
        mqParam.setOperType(MqSyncOperatorTypeEnum.COP_SYNC_KF_SERVICER_LIST.getCode());
        mqParam.setTenantId(Long.valueOf(tenantId));
        mqParam.setAccountId(accountId);
        mqParam.setOpenKfId(kfAccountDo.getOpenKfid());
        mqServiceImpl.sendSyncToWxTaskMessage(mqParam);
        return 1;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer saveOrUpdateOrDeleteBatchKfServicer(Long tenantId, Long kfAccountId, List<KfServicerParam> params){
        if(kfAccountId == null) throw new BusinessException("读取客服id参数出错");
        if(Collections3.isNotEmpty(params)) {
            List<Long> KfServicerIds = new ArrayList<>();
            List<KfServicerDO> needInsertKfServicerDOS = new ArrayList<>();
            List<KfServicerDO> needUpdateKfServicerDOS = new ArrayList<>();
            List<KfServicerDO> needDeleteKfServicerDOS = new ArrayList<>();
            Map<String, Long> KfServicerEmployeeCodeAndIdMap = null;

            List<KfServicerDO> oldKfServicerDOS = KfServicerMapper.selectList(new LambdaQueryWrapper<KfServicerDO>().eq(KfServicerDO::getAccountId, kfAccountId));
            if(Collections3.isNotEmpty(oldKfServicerDOS)) {
                KfServicerEmployeeCodeAndIdMap = oldKfServicerDOS.parallelStream().collect(Collectors.toMap(KfServicerDO::getEmployeeCode,KfServicerDO::getId, (o, n) -> o));
                List<String> oldOpenKfList = oldKfServicerDOS.parallelStream().map(KfServicerDO::getEmployeeCode).collect(Collectors.toList());
                List<String> newOpenKfList = params.parallelStream().map(KfServicerParam::getEmployeeCode).collect(Collectors.toList());
                if (Collections3.isNotEmpty(oldOpenKfList) && Collections3.isNotEmpty(newOpenKfList)) {
                    HashSet<String> oldOpenKfHash = new HashSet<>(oldOpenKfList);
                    HashSet<String> newOpenKfHash = new HashSet<>(newOpenKfList);
                    oldOpenKfHash.removeAll(newOpenKfHash);
                    if (oldOpenKfHash.size() > 0) {
                        List<String> needDeleteOpenKfIds = new ArrayList<>(oldOpenKfHash);
                        needDeleteKfServicerDOS = KfServicerMapper.selectList(new LambdaQueryWrapper<KfServicerDO>().in(KfServicerDO::getEmployeeCode, needDeleteOpenKfIds));
                    }
                }
            }
            List<CopEmployeeDO> copEmployeeDOList = copEmployeeMapper.selectList(new LambdaQueryWrapper<CopEmployeeDO>());
            Map<String, CopEmployeeDO> copEmployeeNameMaps = Collections3.isNotEmpty(copEmployeeDOList)?copEmployeeDOList.stream().collect(Collectors.toMap(CopEmployeeDO::getEmployeeCode, x->x, (o, n) -> n)):null;

            for(KfServicerParam servicerParam : params){
                Long servicerId = 0L;
                KfServicerDO KfServicerDO = BeanUtil.convertBean(servicerParam, KfServicerDO.class);

                KfServicerDO.setSyncStatus(SyncStatusEnum.SYNC_YES.getValue());
                String employeeCode = servicerParam.getEmployeeCode();

                if(KfServicerEmployeeCodeAndIdMap != null && KfServicerEmployeeCodeAndIdMap.containsKey(employeeCode)){
                    servicerId = KfServicerEmployeeCodeAndIdMap.get(employeeCode);
                    KfServicerDO.setId(servicerId);
                    KfServicerDO.setStatus(servicerParam.getStatus());
                    KfServicerDO.setModifyTime(LocalDateTime.now());
                    if(copEmployeeNameMaps !=null){
                        CopEmployeeDO copEmployeeDO = copEmployeeNameMaps.get(employeeCode);
                        KfServicerDO.setEmployeeId(copEmployeeDO.getId());
                        KfServicerDO.setDepartmentId(copEmployeeDO.getMainDepartmentId());
                    }
                    needUpdateKfServicerDOS.add(KfServicerDO);
                    KfServicerIds.add(servicerId);
                }else{
                    KfServicerDO.setCreateTime(LocalDateTime.now());
                    KfServicerDO.setModifyTime(LocalDateTime.now());
                    servicerId = IdGenerator.getId();
                    KfServicerDO.setId(servicerId);
                    KfServicerDO.setOpenKfid(servicerParam.getOpenKfid());
                    KfServicerDO.setAccountId(kfAccountId);
                    KfServicerDO.setStatus(servicerParam.getStatus());
                    KfServicerDO.setEmployeeCode(employeeCode);
                    if(copEmployeeNameMaps !=null){
                        CopEmployeeDO copEmployeeDO = copEmployeeNameMaps.get(employeeCode);
                        KfServicerDO.setEmployeeId(copEmployeeDO.getId());
                        KfServicerDO.setDepartmentId(copEmployeeDO.getMainDepartmentId());
                    }
                    needInsertKfServicerDOS.add(KfServicerDO);
                    KfServicerIds.add(servicerId);
                }
            }
            if(Collections3.isNotEmpty(needDeleteKfServicerDOS)){
                List<Long> delIds = needDeleteKfServicerDOS.stream().map(KfServicerDO::getId).collect(Collectors.toList());
                KfServicerMapper.deleteBatchIds(delIds);
            }

            if(Collections3.isNotEmpty(needInsertKfServicerDOS)){
                KfServicerMapper.insertBatchSomeColumn(needInsertKfServicerDOS);
            }
            if(Collections3.isNotEmpty(needUpdateKfServicerDOS)){
                super.updateBatchById(needUpdateKfServicerDOS);
            }

        }
        return 1;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer syncKfServicerToWxCp(Long id, Long accountId, Boolean deleted){
        String tenantId = UserUtils.getTenantId();
        KfServicerDO entityDO = KfServicerMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        String openKfid = entityDO.getOpenKfid();

        WxCpService wxCpService = wxOpenServiceImpl.getWxCpService(Long.valueOf(tenantId));
        WxCpRedissonConfigImpl wxCpConfigStorage = (WxCpRedissonConfigImpl)wxCpService.getWxCpConfigStorage();
        if (wxCpConfigStorage == null) {
            throw new BusinessException("获取企微服务失败!");
        }
        wxCpConfigStorage.setCorpSecret("A5pyzWIcAe1wpvKs4R69JVhZeygB1TI8vnbc7g8BU90");
        try {
            String wxCpAccessToken = wxCpService.getAccessToken(true);
            wxCpConfigStorage.updateAccessToken(wxCpAccessToken, 7200);
            wxCpService.setWxCpConfigStorage(wxCpConfigStorage);
        }catch(Exception ex){}
        String corpId = wxCpConfigStorage.getCorpId();
        Integer agentId = wxCpConfigStorage.getAgentId();

        WxCpKfService wxCpKfService = wxCpService.getKfService();
        if (wxCpKfService == null) throw new BusinessException("获取客服服务出错!");

        if(deleted){
            try {
                if(agentId == null) return 0;
                if (StringUtils.isEmpty(openKfid)) return 0;
                List<String> servicerList = new ArrayList<>();
                servicerList.add(entityDO.getEmployeeCode());
                WxCpKfServicerOpResp wxCpBaseResp = wxCpKfService.delServicer(openKfid, servicerList);
                if (!wxCpBaseResp.success()) {
                    return 0;
                }else{
                    List<WxCpKfServicerOpResp.WxCpKfServicerResp> wxCpKfServicerResp= wxCpBaseResp.getResultList();

                }
            } catch (WxErrorException ex) {
                return 0;
            }
        }else {
            try {
                List<String> servicerList = new ArrayList<>();
                servicerList.add(entityDO.getEmployeeCode());
                WxCpKfServicerOpResp wxCpKfServicerOpResp = wxCpKfService.addServicer(openKfid,servicerList);
                if (wxCpKfServicerOpResp.success()) {
                    List<WxCpKfServicerOpResp.WxCpKfServicerResp> wxCpKfServicerResp= wxCpKfServicerOpResp.getResultList();
                    if(Collections3.isNotEmpty(wxCpKfServicerResp)){
                       String employeeCode = wxCpKfServicerResp.get(0).getUserId();
                       if(StringUtils.equalsAnyIgnoreCase(employeeCode, entityDO.getEmployeeCode())){
                           entityDO.setSyncStatus(SyncStatusEnum.SYNC_YES.getValue());
                       }else{
                           entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
                       }
                    }else{
                        entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
                    }
                } else {
                    entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
                }
            } catch (WxErrorException ex) {
                LogUtils.error("同步客服接待出错" + ex);
                entityDO.setSyncStatus(SyncStatusEnum.SYNC_NO.getValue());
            }
            if (entityDO != null) {
                KfServicerMapper.updateById(entityDO);
            }
        }
        return 1;
    }
    /**
     * 校验唯一性
     *
     * @param param
     */
    public void checkUnique(KfServicerParam param) {
        if (param == null) {
            throw new BusinessException("当前记录不存在!");
        }
        //code name确保等级唯一性
        LambdaQueryWrapper<KfServicerDO> queryWrapper = new LambdaQueryWrapper<KfServicerDO>()
                .ne(param.getId() != null, KfServicerDO::getId, param.getId())
                .eq(KfServicerDO::getOpenKfid, param.getOpenKfid())
                .eq(KfServicerDO::getEmployeeCode, param.getEmployeeCode());
        List<KfServicerDO> dos = KfServicerMapper.selectList(queryWrapper);
        if (Collections3.isNotEmpty(dos)) {
            throw new BusinessException("已经存在同名的记录!");
        }
    }

    private IKfServicerService getBean(){
        return SpringBeanUtil.getBean(KfServicerServiceImpl.class);
    }
}
